import os
import random
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import *
from core.captcha_solver import CaptchaSolver as CS
from selenium.webdriver.common.keys import Keys

"""
主要是：上传vip文档；
需要传入文档路径folder_path。上传次数。可能还有其他的（）
原力任务的逻辑还未定，比如传入标题上传？自动化上传？待定。
"""


class TaskExecutor:

	def __init__(self, driver, folder_path=None, upload_limit=10, task_type=1, ac=None):
		"""
		driver:打开到指定页面的浏览器对象；
		folder_path：采用默认值暂时,vip1使用；
		upload_limit:上传次数
		ac:api_client，负责和服务器通讯，原力任务时使用
		"""
		self.driver = driver
		self.folder_path = folder_path
		if not self.folder_path:
			if task_type == 1:
				self.folder_path = folder_path if folder_path else os.path.join(os.getcwd(), "vip_files")
			if task_type == 2:
				self.folder_path = folder_path if folder_path else os.path.join(os.getcwd(), "task_files")

		self.upload_limit = upload_limit
		self.error_num = 0  # 错误次数
		self.ac = ac
		self.task_able = True
		self.task_type = task_type  # 任务类型，1是vip文档上传；2是定产vip上传
		if self.task_type == 1:
			self.upload_vip_file()
		elif self.task_type == 2:
			self.upload_vip2_file()

	# 正常上传vip文档
	def upload_vip_file(self):
		print("========================================================================================")
		print(f"VIP文档任务开始，计划上传{self.upload_limit}次，文件目录为 {self.folder_path}")
		print("========================================================================================")
		files_list = []
		for root, dirs, files in os.walk(self.folder_path):
			for file in files:
				files_list.append(os.path.join(root, file))
		if not files_list:
			print("文件夹中没有找到文件，上传任务结束。")
			return
		random.shuffle(files_list)
		for count, file_path in enumerate(files_list, 1):
			print(f"----------开始上传第 {count} 个文档----------")
			if not self.upload_file(file_path):
				print("终止文件上传过程，请检查下原因。")
				break
			print(f"已完成 {count} 个文档上传")
			time.sleep(random.randint(5, 20))
			if count >= self.upload_limit:
				print(
					"==========================================上传完成累计{count} 个==============================================")
				break

	# 原力任务--
	def upload_vip2_file(self):
		i = 1
		for filename in os.listdir(self.folder_path):
			# 获取不带后缀的文件名
			if not self.task_able:
				print("===========今日任务已完成==========")
				break
			base_filename = os.path.splitext(filename)[0]
			titles = self.ac.get_data(endpoint="/api/wenku/titles/get_titles_list", title_name=base_filename,limitNum=1)
			if not len(titles):
				print(f"无法在数据库中找到相关任务：{filename}")
				continue
			data = titles[0]
			print(f"开始进行任务：{data["article_name"]}")
			# self.driver为selenium浏览器对象，在当前页面中，找到div.major-type-line > div.privilege-list-wraper > div > div.slider-list下面的div.privilege-item-container,div有多个，
			# 判断，如果data['article_type'] > 20,则无操作。否则点击 第{data['article_type']+2}个div。
			err_num = 0
			while True:
				if not self.task_able:
					print("===========今日任务已完成==========")
					break
				self.driver.refresh()
				if err_num >= 5:
					print("上传累计错误5次，结束任务")
					break
				containers = self.driver.find_elements(By.CSS_SELECTOR, '.privilege-item-container')
				if data['article_type'] < 20:
					target_index = data['article_type'] + 2
					if target_index <= len(containers):
						containers[target_index - 1].click()  # 索引从0开始
				print(f"---切换到分类，分类标识：{data['article_type']}")
				time.sleep(10)  # 等待10秒
				# 等待10秒钟，在页面中找到div.pagination元素下找到一个input【type=number】的输入框，在里面输入{data['page_number']+1},并按回车或表单失去焦点，跳转到对应的页面
				# 输入页码并跳转
				pagination_input = WebDriverWait(self.driver, 20).until(
					EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.pagination input[type=number]'))
				)
				# pagination_input.clear()
				pagination_input.send_keys(str(data['page_number'] + 1))
				pagination_input.send_keys(Keys.ENTER)  # 或pagination_input.send_keys(Keys.TAB)来失去焦点
				print(f"---定位到页面，页码：{data['page_number'] + 1}")

				time.sleep(3)  # 等待10秒
				# 等待10秒钟，在页面中找到 div.doc-wrapper 元素下的第{data['page_sort_number']}个div.doc-row， 找到其下面的span.complete-status，如果span的display=none,则继续
				doc_rows = self.driver.find_elements(By.CSS_SELECTOR, 'div.doc-wrapper div.doc-row')
				target_doc_row = doc_rows[data['page_sort_number'] - 1] if data['page_sort_number'] <= len(doc_rows) else None
				if target_doc_row:

					# 还要找到input，
					try:
						file_input = target_doc_row.find_element(By.CSS_SELECTOR, 'input[type=file]')
						print("找到了文件的input")
					except Exception:
						self.driver.save_screenshot('无法上传了.png')
						self.task_able = False
						print("今日已达上限111")
						break
					status_span = target_doc_row.find_element(By.CSS_SELECTOR, 'span.complete-status')
					if 'none' not in status_span.get_attribute('style').lower():
						print("此任务已完成")
						break
					else:
						print("已经定位到任务；；；；接下来，就是上传了")
						res = self.upload_file2(filename,file_input)
						if not res: #验证码、无权限等
							err_num += 1
							continue
				else:
					print("未找到对应的文档行")
					break
			print(f"===================已完成第{i}个任务====================")
			i += 1
	# 下载任务文档---待迁移
	def download_vip_file(self, docs, num=0):
		random.shuffle(docs)
		# 循环访问页面并下载
		download_count = 0  # 已下载的文档数量
		max_download_count = num  # 最大下载次数限制
		for doc in docs:
			if download_count >= max_download_count:
				print("已达到最大下载次数，结束下载")
				break
			if doc['doc_status'] != 2:
				continue
			doc_id = doc['doc_id']
			if doc['doc_status'] != 2:
				continue
			timestamp = int(time.time() * 1000)  # 获取13位时间戳?{timestamp}
			url = f'https://wenku.baidu.com/view/{doc_id}.html?_wkts_={timestamp}'
			self.driver.get(url)
			time.sleep(5)
			if "seccaptcha.baidu.com" in self.driver.current_url:
				print("出现了验证码...")
				self.handle_captcha()
			time.sleep(5)
			try:
				download_button = self.driver.find_element(By.CSS_SELECTOR, 'div.drop-down + .btn-normal')
				print(download_button)
				print(download_button.text)
				if '单篇下载' in download_button.text:
					download_button.click()
					print(f"第{download_count + 1}个VIP文档下载成功")
					download_count += 1
				else:
					if '重新下载' in download_button.text:
						print(f"文档 {doc_id} 已经下载过")
			except Exception as e:
				print(f"文档 {doc_id} 下载失败: {e}")
			time.sleep(10)  # 等待3秒再进行下一个下载

	def upload_file(self, file_path):
		if self.error_num == 5:
			print("连续出错5次,请分析原因")
			return False
		try:
			file_input = WebDriverWait(self.driver, 20).until(
				EC.presence_of_element_located((By.CSS_SELECTOR, ".file-selector-input"))
			)
		except TimeoutException:
			self.driver.save_screenshot('无法上传查看.png')
			print("今日已达上限")
			return False
		# 表单赋值
		file_input.send_keys(file_path)
		time.sleep(5)
		# 判断是否出现了验证码
		if "seccaptcha.baidu.com" in self.driver.current_url:
			print("==============================开始处理验证码==============================")
			self.handle_captcha()
			# self.driver.refresh()
			return self.upload_file(file_path)
		# 会出现遮罩层
		try:
			WebDriverWait(self.driver, 30).until(
				EC.invisibility_of_element_located((By.CSS_SELECTOR, ".el-loading-mask"))
			)
		except TimeoutException:
			print("等待遮罩层消失超时，已保存错误截图，即将重试。")
			self.driver.save_screenshot('一直显示上传中.png')
			self.error_num += 1
			return self.upload_file(file_path)

		try:
			radio_select = WebDriverWait(self.driver, 30).until(
				EC.element_to_be_clickable((By.CSS_SELECTOR, ".el-radio:nth-child(3) .el-radio__inner"))
			)
			time.sleep(1)
			## 使用JavaScript来点击元素，以绕过可能的遮罩层问题#self.driver.execute_script("arguments[0].click();", radio_select)
			try:
				radio_select.click()
			except Exception:
				print("=================出现了错误,test1.png=============")
				self.driver.save_screenshot('test1.png')
				self.driver.refresh()
		except TimeoutException:
			print("文件检查无效，请核实")
			self.driver.save_screenshot('文件检查无效.png')
			self.error_num += 1
			self.driver.refresh()
			return self.upload_file(file_path)

		try:
			submit_button = WebDriverWait(self.driver, 20).until(
				EC.element_to_be_clickable((By.CSS_SELECTOR, ".doc-upload-btn-bar > .el-button > span"))
			)
			submit_button.click()
		except TimeoutException:
			print("确认提交按钮无法点击，请查看截图")
			self.driver.save_screenshot('确认提交按钮无法点击.png')
			self.error_num += 1
			self.driver.refresh()
			return self.upload_file(file_path)

		# 检查上传结果
		try:
			success_dialog = WebDriverWait(self.driver, 20).until(
				EC.presence_of_element_located((By.CSS_SELECTOR, ".upload-dialog-footer > .el-button"))
			)
			success_dialog.click()
			os.remove(file_path)
			print(f"{file_path} 上传成功并已删除")
		except TimeoutException:
			print(f"{file_path}上传失败")
			self.driver.save_screenshot('确认上传后出错.png')
			self.error_num += 1
			self.driver.refresh()
			return self.upload_file(file_path)
		return True  # 返回 True 表示成功上传

	def upload_file2(self, file_path,file_input):
		#找到指定的

		file_input.send_keys(file_path)
		time.sleep(5)
		# 判断是否出现了验证码
		if "seccaptcha.baidu.com" in self.driver.current_url:
			print("==============================开始处理验证码==============================")
			self.handle_captcha()
			return False
		# 会出现遮罩层
		try:
			WebDriverWait(self.driver, 30).until(
				EC.invisibility_of_element_located((By.CSS_SELECTOR, ".el-loading-mask"))
			)
		except TimeoutException:
			print("等待遮罩层消失超时，已保存错误截图，即将重试。")
			self.driver.save_screenshot('一直显示上传中.png')
			return False

		print("--------------------------------正在等待手动确认--------------------------------")
		time.sleep(600)

		try:
			submit_button = WebDriverWait(self.driver, 20).until(
				EC.element_to_be_clickable((By.CSS_SELECTOR, ".doc-upload-btn-bar > .el-button > span"))
			)
			submit_button.click()
		except TimeoutException:
			print("确认提交按钮无法点击，请查看截图")
			self.driver.save_screenshot('确认提交按钮无法点击.png')
			return False
		# 检查上传结果
		try:
			success_dialog = WebDriverWait(self.driver, 20).until(
				EC.presence_of_element_located((By.CSS_SELECTOR, ".upload-dialog-footer > .el-button"))
			)
			success_dialog.click()
			os.remove(file_path)
			print(f"{file_path} 上传成功并已删除")
		except TimeoutException:
			print(f"{file_path}上传失败")
			self.driver.save_screenshot('确认上传后出错.png')
			return False
		return True  # 返回 True 表示成功上传

	def handle_captcha(self):
		CS(self.driver)
		# 调用本级目录下的

		return


if __name__ == "__main__":
	# TaskExecutor()
	print(111)
